<template>
  <div class="pt-80">
    <div style="height: 20vh" class="bg-blue-400"></div>
    <div ref="scene" class="scene"></div>
    <div style="height: 200vh" class="bg-blue-400"></div>
  </div>
</template>

<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount, useTemplateRef } from "vue";
import Matter from "matter-js";
import { useIntersectionObserver } from "@vueuse/core";

// 场景引用
const scene = useTemplateRef<HTMLDivElement>("scene");
// 要展示的单词
const words = [
  "Hello",
  "World",
  "Matter",
  "Physics",
  "Animation",
  "JavaScript",
  "Vue",
  "Nuxt",
];
// Matter.js 实例
let engine: Matter.Engine, render: Matter.Render, runner: Matter.Runner;
let wordBodies: string[] = [];
let observer: IntersectionObserver | null = null;
const canvasH = 600;
let checkBoundsTimer: any = null;
// 定义全局的滚动处理函数

// 清理物理引擎和动画
const cleanupPhysics = () => {
  // 停止运行
  if (runner) Matter.Runner.stop(runner); // 修复：正确停止运行器
  if (render) Matter.Render.stop(render);
  if (engine) Matter.Engine.clear(engine);
  // 清空场景元素
  if (scene.value) {
    while (scene.value.firstChild) {
      scene.value.removeChild(scene.value.firstChild);
    }
  }

  // 清理定时器
  if (checkBoundsTimer) {
    clearInterval(checkBoundsTimer);
    checkBoundsTimer = null;
  }

  // 重置变量
  engine = null;
  render = null;
  runner = null;
  wordBodies = [];
};

// 随机颜色函数
const getRandomColor = () => {
  const colors = [
    "#FFD6E0",
    "#FFEFCF",
    "#D1F0FF",
    "#C9E4DE",
    "#EDEEC9",
    "#DFD3C3",
    "#F0DBDB",
    "#D5E3F0",
    "#E0F0D5",
    "#F0E5D5",
  ];
  return colors[Math.floor(Math.random() * colors.length)];
};

onMounted(() => {
  // 创建 Intersection Observer 来监测元素可见性
  if (IntersectionObserver && window !== undefined) {
    observer = new IntersectionObserver(
      (entries) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            // 元素进入视口，初始化物理引擎
            initPhysics();
          } else {
            // 元素离开视口，清理物理引擎
            cleanupPhysics();
          }
        });
      },
      {
        threshold: 0.1, // 当10%的元素可见时触发
      }
    );

    // 开始观察场景元素
    if (scene.value) {
      observer.observe(scene.value);
    }
  }
});

onBeforeUnmount(() => {
  // 停止观察
  if (observer && scene.value) {
    observer.unobserve(scene.value);
    observer.disconnect();
  }

  // 清理物理引擎
  cleanupPhysics();

  // 移除事件监听器
  window.removeEventListener("resize", handleResize);
});

// 窗口大小变化处理函数
const handleResize = () => {
  if (render) {
    render.options.width = window.innerWidth;
    render.options.height = canvasH;
    render.canvas.width = window.innerWidth;
    render.canvas.height = canvasH;
  }
};

// 在initPhysics函数中添加边界检测和标签重生功能
const initPhysics = () => {
  if (typeof window === "undefined" || !scene.value) return;

  // 清理之前的实例（如果存在）
  cleanupPhysics();

  // 初始化 Matter.js
  const Engine = Matter.Engine;
  const Render = Matter.Render;
  const Runner = Matter.Runner;
  const Bodies = Matter.Bodies;
  const Composite = Matter.Composite;
  const Common = Matter.Common;
  // 添加鼠标约束相关模块
  const Mouse = Matter.Mouse;
  const MouseConstraint = Matter.MouseConstraint;

  // 创建引擎
  engine = Engine.create();

  // 创建渲染器
  render = Render.create({
    element: scene.value as HTMLElement,
    engine: engine,
    options: {
      width: window.innerWidth,
      height: canvasH,
      wireframes: false,
      background: "#f5f5f5",
    },
  });

  // 创建交互层
  // const interactionLayer = document.createElement("div");
  // interactionLayer.className = "interaction-layer";
  // scene.value.appendChild(interactionLayer);

  // 创建边界墙
  const ground = Bodies.rectangle(window.innerWidth / 2, canvasH, window.innerWidth, 20, {
    isStatic: true,
    // render: { fillStyle: "red" },
    render: { fillStyle: "transparent" },
  });

  // 修改左侧边界墙，将其位置设置在画布左侧之外，并增加宽度
  const leftWall = Bodies.rectangle(0, canvasH / 2, 60, canvasH * 2, {
    isStatic: true,
    render: { fillStyle: "transparent" }, // 改回透明
  });

  const rightWall = Bodies.rectangle(window.innerWidth, canvasH / 2, 60, canvasH * 2, {
    isStatic: true,
    render: { fillStyle: "transparent" },
  });

  // 添加顶部边界墙
  const ceiling = Bodies.rectangle(
    window.innerWidth / 2,
    -250, // 位于画布上方
    window.innerWidth * 1.5,
    60,
    {
      isStatic: true,
      render: { fillStyle: "transparent" },
    }
  );

  // 添加边界墙到世界
  Composite.add(engine.world, [ground, leftWall, rightWall, ceiling]);

  // 添加一个黑色小球作为位置参考
  const referenceCircle = Bodies.circle(50, 50, 15, {
    isStatic: true,
    render: {
      fillStyle: "#000000",
      strokeStyle: "#ffffff",
      lineWidth: 2,
    },
  });
  Composite.add(engine.world, referenceCircle);

  // 移除重复的添加边界墙代码
  // Composite.add(engine.world, [ground, leftWall, rightWall]);

  // 初始添加单词 - 只添加10个单词
  // 从words数组中随机选择10个单词（如果words少于10个，则全部使用）
  const selectedWords = [...words];
  // 如果单词数量超过10个，随机选择10个
  if (selectedWords.length > 10) {
    // Fisher-Yates 洗牌算法
    for (let i = selectedWords.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      [selectedWords[i], selectedWords[j]] = [selectedWords[j], selectedWords[i]];
    }
    selectedWords.splice(10); // 只保留前10个
  }

  // 添加选定的单词
  wordBodies = [];
  selectedWords.forEach((word) => {
    const wordBody = createWord(word);
    wordBodies.push(wordBody);
    Composite.add(engine.world, wordBody);
  });

  // 添加定时器检查标签是否超出边界，并重新添加
  const checkBounds = () => {
    if (!engine || !render) return;

    const bodies = Composite.allBodies(engine.world);
    const viewportHeight = canvasH;
    const viewportWidth = window.innerWidth;

    // 检查每个非静态物体
    for (let i = bodies.length - 1; i >= 0; i--) {
      const body = bodies[i];
      if (body.isStatic) continue;

      // 检查是否超出边界
      if (
        body.position.y > viewportHeight + 100 || // 底部
        body.position.y < -200 || // 顶部
        body.position.x < -100 || // 左侧
        body.position.x > viewportWidth + 100
      ) {
        // 右侧

        // 从世界中移除
        Composite.remove(engine.world, body);

        // 从数组中移除
        const index = wordBodies.indexOf(body);
        if (index !== -1) {
          wordBodies.splice(index, 1);
        }

        // 创建新的单词替代
        if (body.plugin && body.plugin.textWord) {
          const newWordBody = createWord(body.plugin.textWord);
          wordBodies.push(newWordBody);
          Composite.add(engine.world, newWordBody);
        }
      }
    }

    // 确保始终有足够的单词
    if (wordBodies.length < selectedWords.length) {
      const missingCount = selectedWords.length - wordBodies.length;
      for (let i = 0; i < missingCount; i++) {
        const randomWord = words[Math.floor(Math.random() * words.length)];
        const newWordBody = createWord(randomWord);
        wordBodies.push(newWordBody);
        Composite.add(engine.world, newWordBody);
      }
    }
  };

  // 设置定时器，每秒检查一次
  checkBoundsTimer = setInterval(checkBounds, 1500);

  // 运行引擎和渲染器
  Render.run(render);
  runner = Runner.create();
  Runner.run(runner, engine);

  // 添加鼠标控制
  // 创建鼠标交互
  const mouse = Mouse.create(render.canvas);
  const mouseConstraint = MouseConstraint.create(engine, {
    mouse: mouse,
    constraint: {
      stiffness: 0.2,
      render: {
        visible: false,
      },
    },
  });

  // 修改鼠标事件处理，允许滚动
  mouse.element.removeEventListener("mousewheel", mouse.mousewheel);
  mouse.element.removeEventListener("DOMMouseScroll", mouse.mousewheel);

  // 添加自定义鼠标滚轮处理
  let scrollTimeout: any;
  const customMousewheel = function (event: any) {
    render.canvas.style.pointerEvents = "none";
    if (scrollTimeout) {
      clearTimeout(scrollTimeout);
      scrollTimeout = null;
    }

    scrollTimeout = setTimeout(() => {
      render.canvas.style.pointerEvents = "auto";
    }, 200);
  };

  // 使用自定义处理函数
  mouse.element.addEventListener("mousewheel", customMousewheel, {
    passive: true,
  });
  mouse.element.addEventListener("wheel", customMousewheel, {
    passive: true,
  });
  mouse.element.addEventListener("DOMMouseScroll", customMousewheel, {
    passive: true,
  });

  // 添加鼠标约束到世界
  Composite.add(engine.world, mouseConstraint);

  // 确保渲染器的鼠标同步
  render.mouse = mouse;

  // 添加自定义渲染逻辑来绘制文本
  Matter.Events.on(render, "afterRender", () => {
    const context = render.context;
    const bodies = Composite.allBodies(engine.world);

    context.font = "bold 24px Arial";
    context.textAlign = "center";
    context.textBaseline = "middle";

    for (let i = 0; i < bodies.length; i++) {
      const body = bodies[i];
      // 跳过边界墙体
      if (body.isStatic) continue;

      // 使用 plugin 属性获取文本信息
      if (body.plugin && body.plugin.textWord) {
        context.font = `bold ${body.plugin.textSize}px Arial`;
        context.fillStyle = "#0c41b2";
        context.fillText(body.plugin.textWord, body.position.x, body.position.y);
      }
    }
  });

  // 窗口大小变化时调整渲染器大小
  window.addEventListener("resize", handleResize);
};

// 创建单词函数
const createWord = (word: string) => {
  const fontSize = 20 + Math.random() * 20; // 随机字体大小

  // 创建临时 DOM 元素测量文本宽度
  const tempEl = document.createElement("div");
  tempEl.style.position = "absolute";
  tempEl.style.visibility = "hidden";
  tempEl.style.fontSize = `${fontSize}px`;
  tempEl.style.fontWeight = "bold";
  tempEl.style.fontFamily = "Arial, sans-serif";
  tempEl.innerText = word;
  document.body.appendChild(tempEl);

  const width = tempEl.offsetWidth + 20;
  const height = fontSize * 1.5;
  document.body.removeChild(tempEl);

  // 随机位置
  const x = 30 + Math.random() * (window.innerWidth - 100);
  const y = -100 - Math.random() * 200; // 在视口上方

  // 创建矩形物体
  const body = Matter.Bodies.rectangle(x, y, width, height, {
    restitution: 0.6, // 弹性
    friction: 0.1,
    chamfer: {
      radius: 10,
    },
    render: {
      fillStyle: getRandomColor(),
    },
    // 使用 plugin 属性存储自定义数据
    plugin: {
      textWord: word,
      textSize: fontSize,
    },
  });

  return body;
};
</script>

<style lang="scss">
.container {
  width: 100%;
  overflow: hidden;
}

.scene {
  width: 100vw;
  height: 600px;
  overflow: hidden;
  position: relative;
  canvas {
    max-width: 100%;
    touch-action: pan-y; /* 允许垂直滚动，但保持水平拖动功能 */
  }
  .interaction-layer {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    touch-action: pan-y;
    pointer-events: none;
    background-color: rgba(134, 30, 30, 0.2);
  }
}

/* 移除不需要的交互层样式 */
</style>
